/*
 * 在Orchard模块中创建RESTful Web API与创建MVC控制器非常相似，基本上与在纯ASP.NET Core中创建API相同
 * （请参阅相关教程：https://docs.microsoft.com/en-us/aspnet/core/web-api/）。让我们看一个基本示例！
 * 
 * 注意：Orchard开箱即用也提供了Web API：有许多RESTful API端点可用于内容和租户管理，
 * 以及许多模块贡献的GraphQL API基础设施（请参阅：https://docs.orchardcore.net/en/latest/docs/reference/modules/Apis.GraphQL/），
 * 您也可以扩展它。
 * 
 * 主要功能：
 * - 提供RESTful API端点
 * - 演示Orchard Core API集成
 * - 展示权限控制和授权机制
 * - 支持内容项的API访问
 */

using Lombiq.TrainingDemo.Permissions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using OrchardCore.ContentManagement;
using System.Threading.Tasks;

namespace Lombiq.TrainingDemo.Controllers;

/// <summary>
/// API控制器 - 提供RESTful Web API功能
/// 
/// 主要用途：
/// - 为PersonPage内容项提供API访问
/// - 演示Orchard Core API集成方式
/// - 展示API权限控制和授权机制
/// - 提供内容项的JSON表示
/// 
/// 使用场景：
/// - Web SPA应用访问内容数据
/// - 移动应用获取内容信息
/// - 第三方系统集成
/// - API客户端测试和验证
/// 
/// 设计原因：
/// - 遵循ASP.NET Core Web API最佳实践
/// - 使用属性路由提供标准化的API端点
/// - 集成Orchard Core的权限系统
/// - 提供安全的内容访问机制
/// 
/// 设计模式：
/// - RESTful API模式：使用标准HTTP方法和状态码
/// - 授权模式：使用IAuthorizationService进行权限检查
/// - 依赖注入模式：通过构造函数注入所需服务
/// - 内容管理模式：使用IContentManager管理内容项
/// </summary>
// 这个控制器将为我们检索Person Page内容项作为简单示例，尽管如此，它展示了您需要了解的最重要的事情。
// 如果您想查看更复杂的此类控制器示例，请查看官方源代码中OrchardCore.Content模块的ApiController。

// 使用属性路由为这个控制器中的所有操作提供正确的路由。
[Route("api/Lombiq.TrainingDemo")]
// ApiController属性不是严格强制性的，但非常有用，请参阅：
// https://docs.microsoft.com/en-us/aspnet/core/web-api/#apicontroller-attribute
[ApiController]
// 我们将在操作（即API端点）中处理授权，所以这里不需要其他内容。注意API端点应该大多数时候使用"Api"认证方案：
// 这与标准用户通过cookie认证的方式不同。
[Authorize(AuthenticationSchemes = "Api"), IgnoreAntiforgeryToken, AllowAnonymous]
public sealed class ApiController : ControllerBase
{
    private readonly IAuthorizationService _authorizationService;
    private readonly IContentManager _contentManager;

    /// <summary>
    /// 构造函数 - 注入所需的服务依赖
    /// </summary>
    /// <param name="authorizationService">授权服务，用于API权限检查</param>
    /// <param name="contentManager">内容管理器，用于获取和管理内容项</param>
    public ApiController(IAuthorizationService authorizationService, IContentManager contentManager)
    {
        _authorizationService = authorizationService;
        _contentManager = contentManager;
    }

    /// <summary>
    /// 获取PersonPage内容项
    /// 
    /// 功能说明：
    /// - 根据内容项ID获取PersonPage内容项
    /// - 进行权限检查确保用户有管理权限
    /// - 返回内容项的JSON表示
    /// 
    /// 权限要求：
    /// - 需要ManagePersons权限
    /// - 无权限时返回401未授权状态
    /// 
    /// 访问方式：
    /// - GET /api/Lombiq.TrainingDemo?contentItemId={contentItemId}
    /// - 需要OpenID应用设置的客户端ID和密钥进行认证
    /// 
    /// 参数说明：
    /// - contentItemId：要获取的内容项ID
    /// 
    /// 返回值：
    /// - 成功：返回内容项的JSON表示
    /// - 未找到：返回404状态码
    /// - 无权限：返回401状态码
    /// </summary>
    /// <param name="contentItemId">内容项ID</param>
    /// <returns>内容项的JSON表示或错误状态</returns>
    // 您可以查找之前创建的Person Page的ID（当您从管理内容项列表中打开一个时，URL将包含它作为/Admin/Contents/ContentItems/<content item ID>）
    // 并使用它来访问此操作，地址为/api/Lombiq.TrainingDemo?contentItemId=<content item ID>。
    // 但请注意，您只能使用从Orchard管理界面设置的OpenID应用的客户端ID和密钥进行授权。
    // 更多信息请参阅：https://docs.orchardcore.net/en/latest/docs/reference/modules/OpenId/。
    // 如果您只想快速测试此API，请删除上面的Authorize属性。
    [HttpGet]
    public async Task<IActionResult> Get(string contentItemId)
    {
        // 在API端点中授权也很重要。我们在这里重用之前创建的权限。
        // 要使用API进行身份验证，您可以使用任何ASP.NET Core身份验证方案，但Orchard提供各种基于OpenID的选项。
        // 如果您只想快速查看API，请在管理界面上为Anonymous角色授予权限。
        if (!await _authorizationService.AuthorizeAsync(User, PersonPermissions.ManagePersons))
        {
            return this.ChallengeOrForbid("Api");
        }

        // 再次使用通常的内容管理操作。
        var contentItem = await _contentManager.GetAsync(contentItemId);

        // 只允许检索Person Page项目。
        if (contentItem?.ContentType != ContentTypes.PersonPage) contentItem = null;

        // 操作将自动返回内容项的JSON表示。然后您可以从Web SPA或移动应用程序等消费它。
        return contentItem == null ? NotFound() : Ok(contentItem);
    }
}

// 训练部分结束：Web API

// 下一站：Middlewares/RequestLoggingMiddleware.cs
